/*
 * Copyright (C) 2015 yixun All Rights Reserved.
 * 
 * CustomerInfoServiceImpl.java
 */
package com.yixun.qfbao.service.impl;

import com.yixun.common.page.Page;
import com.yixun.qfbao.mapper.CustomerInfoMapper;
import com.yixun.qfbao.model.Commission;
import com.yixun.qfbao.model.CommissionRuleParent;
import com.yixun.qfbao.model.CommissionRules;
import com.yixun.qfbao.model.CustomerInfo;
import com.yixun.qfbao.model.dto.CommissionDto;
import com.yixun.qfbao.model.dto.CommissionRuleParentDto;
import com.yixun.qfbao.model.dto.CommissionRulesDto;
import com.yixun.qfbao.model.dto.CustomerInfoDto;
import com.yixun.qfbao.model.enums.CommisionModeEnum;
import com.yixun.qfbao.service.CommissionRuleParentService;
import com.yixun.qfbao.service.CommissionRulesService;
import com.yixun.qfbao.service.CommissionService;
import com.yixun.qfbao.service.CustomerInfoService;
import com.yixun.qfbao.xf.model.enums.CommissionStatusEnum;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;


@Service("customerInfoService")
public class CustomerInfoServiceImpl implements CustomerInfoService {
	
	private static Logger logger = Logger.getLogger(CustomerInfoServiceImpl.class);

	@Autowired
	private CustomerInfoMapper mapper;
	@Autowired
	private CommissionRuleParentService commissionRuleParentService;
	@Autowired
	private CommissionRulesService commissionRulesService;
	@Autowired
	private CommissionService commissionService;



	/**
	 * @param entity 搜索条件
	 * @param begin 分页开始行数[不包含]
	 * @param end 分页结束行数[包含]
	 * @return 分页记录
	 */
	@Transactional(readOnly = true)
	public Page<CustomerInfo> getPageModel(CustomerInfoDto entity, int begin, int end){
		Integer total = mapper.count(entity);
		List<CustomerInfo> rows = mapper.list(entity,begin,end);
		Page<CustomerInfo> msr = new Page<CustomerInfo>(total, rows);
		return msr;
	}

	/**
	 * 查询列表
	 * @param entity 搜索条件
	 * @return 分页记录
	 */
	public List<CustomerInfo> selectListByDto(CustomerInfoDto entity){
		return mapper.selectListByDto(entity);
	}

	/**
	 * 查询单个
	 * @param entity 搜索条件
	 * @return 分页记录
	 */
	public CustomerInfo selectByDto(CustomerInfoDto entity){
		return mapper.selectByDto(entity);
	}

	/**
	 * @param id 搜索条件
	 * @return 分页记录
	 */
	public CustomerInfo selectById(Long id){
		if(id!=null){
			return mapper.selectById(id);
		}
		return null;
	}
	/**
	 * @param entity 新增记录的详细信息
	 * @return 新增行数
	 */
	public CustomerInfoDto create(CustomerInfoDto entity) {
		entity.setCreateTime(Calendar.getInstance().getTime());
		mapper.add(entity);
		return entity;
	}

	/**
	 * @param entity 更新记录的详细信息
	 * @return 更新行数
	 */
	public int update(CustomerInfoDto entity) {
		entity.setUpdateTime(Calendar.getInstance().getTime());
		return mapper.edit(entity);
	}

	/**
	 * @param entity 待删除的记录信息
	 * @return 删除行数
	 */
	public int destroy(CustomerInfoDto entity) {
		return mapper.del(entity);
	}

	/**
	 * @param entity 新增或更新
	 * @return 新增行数
	 */
	public int saveOrUpdate(CustomerInfoDto entity) {
		if(entity!=null&&entity.getId()!=null){
			return update(entity);
		}else{
			create(entity);
			return 1;
		}
	}

	/**
	 * @param entity 根据pojo搜索如果主键为空则返回它本身
	 * @return 一行记录或本身
	 */
	@Override
	public CustomerInfo selectBy(CustomerInfo entity) {
		if(entity!=null&&entity.getId()!=null){
			return mapper.selectById(entity.getId());
		}
		return entity;
	}

	/**
	 * 按照规则列表
	 * @param companyId 机构ID
	 * @param premisesId 楼盘ID
	 * @return List<CommissionRules> 规则列表
	 * @author shaoping.jiao
	 */
	@Override
	public List<CommissionRules> getNewRules(Long companyId, Long premisesId) {
		CommissionRuleParentDto crpDto = new CommissionRuleParentDto();
		crpDto.setCompanyId(companyId);
		crpDto.setPremisesId(premisesId);
		//根据机构ID和楼盘ID查询规则公共表里的ID
		CommissionRuleParent commissionRuleParent = commissionRuleParentService.selectByDto(crpDto);
		CommissionRulesDto crDto = new CommissionRulesDto();
		if (commissionRuleParent != null) {
			crDto.setRelationId(commissionRuleParent.getId());
		}else {
			//如果没取到佣金规则信息，则设置realtionid为-1，不能取出规则
			crDto.setRelationId(-1L);
		}
		//设置是否有效
		crDto.setState("1");
		//取生效的规则
		crDto.setEffectTimeAfter(new Date());
		//按照生效时间和sort值倒序排序。
		crDto.setOrders("id desc,effect_time desc, sort desc, commission_type desc;");
		//通过规则公共表ID查询出生效的规则集合，并且根据生效时间排序
		return commissionRulesService.selectListByDto(crDto);
	}
	
	/**
	 * 按照新的方式获取佣金金额或佣金比例
	 * @param companyId 机构ID
	 * @param premisesId 楼盘ID
	 * @param dealAmount 当次成交金额
	 * @param flag 是否计算当次金额
	 * @return CommissionRules 佣金规则
	 * @author shaoping.jiao
	 */
	@Override
	public CommissionRules getNewCommission(Long companyId, Long premisesId, BigDecimal dealAmount, boolean flag, String addOrDel){
		List<CommissionRules> crList = getNewRules(companyId, premisesId);
		if (null == crList || 0 == crList.size()) {
			//当无规则时，给佣金赋值默认为0
			CommissionRules rule = new CommissionRules();
			rule.setCommissionAmmount("0");
			return rule;
		} else {
			CommissionRules rule = crList.get(0);
			//sort等于规则的个数，以后可以动态扩展，无需修改代码
			int length = Integer.parseInt(rule.getSort());
			//获取佣金表里的信息
			Commission commission = selectCommisison(rule.getGroupId(),rule.getRelationId(), companyId, premisesId);
			BigDecimal amount = new BigDecimal(Double.valueOf(0));
			int number = 0;
			if (null != commission) {
				//获取成交总额
				amount = BigDecimal.valueOf(Double.valueOf(commission.getDealAmount()));
				//成交套数
				number = Integer.parseInt(commission.getDealNum());
			}
			//是否计算当次
			if (flag) {
				if("add".equals(addOrDel)){
					number = number + 1;
					amount = amount.add(dealAmount == null ? BigDecimal.ZERO : dealAmount);
				}else{
					amount = amount.subtract(dealAmount == null ? BigDecimal.ZERO : dealAmount);

				}
			}
			//佣金类型:1固定金额，2固定比例，3阶梯成交套数，4阶梯成交总额
			if (CommisionModeEnum.COMMISION_MODE_1.getNo().equals(rule.getCommissionType())) {
				//有三种情况
				//1：List大小=1，这种情况下直接返回rule.getCommissionAmmount()
				//2:List大小>1，且有冲突的同种类规则，由于列表是排序过后的，取最新的，还是返回rule.getCommissionAmmount()
				//3：List大小>1，且月有冲突的不同种类规则，同上，由于是取最新生效的规则，所以还是返回rule.getCommissionAmmount()
				//所以这里直接返回rule
				BigDecimal commissionAmmount = new BigDecimal(rule.getCommissionAmmount());
				rule.setCommissionAmmount(commissionAmmount.multiply(new BigDecimal(number)).toString());
				return rule;
			} else if (CommisionModeEnum.COMMISION_MODE_2.getNo().equals(rule.getCommissionType())) {
				//固定比例
				//同上
				String rate = rule.getCommissionRate();
				rule.setCommissionAmmount(calcAmountByRate(amount, rate));
				return rule;
			} else if (CommisionModeEnum.COMMISION_MODE_3.getNo().equals(rule.getCommissionType())) {
				//只取前几个，可能是1个，2个，3个，以后也可能新增。
				//判断成交套数，在哪个区间，然后取具体的佣金比例
				CommissionRules eRule = getEfficientRule(BigDecimal.valueOf(Double.valueOf(number)),crList,length);
				eRule.setCommissionAmmount(calcAmountByRate(amount, eRule.getCommissionRate()));
				return eRule;
			} else {
				//成交总额
				CommissionRules eRule = getEfficientRule(amount,crList,length);
				eRule.setCommissionAmmount(calcAmountByRate(amount, eRule.getCommissionRate()));
				return eRule;
			}
		}
	}
	
	/**
	 * type类型为3或4时取佣金比例
	 * （不用subList截取数组，为了提高性能，直接用Length从原数组里去取值）
	 * @param number 成交总套数或成交总金额
	 * @param crList 规则List
	 * @param length 从规则List中需要取得有效长度
	 * @return String
	 * @author shaoping.jiao
	 */
	private CommissionRules getEfficientRule(BigDecimal number,List<CommissionRules> crList,int length){
		if(length > crList.size()){
			length = crList.size();
		}
		for(int i = 0; i < length; i++) {
			CommissionRules cRule = crList.get(i);
			String detailRule = cRule.getRule();
			int rLength = detailRule.length();
			//数据库存储的rule格式如下: 
			// ,10 ，表示10以下
			// 10,50表示 介于10到50之间，以后可能会新增区间，但不影响。
			// 50,表示50以上。用英文逗号来区分
			// 所以判断rule的第一位字符和最后一位字符是否是英文逗号，来确定区间
			String firstLetters = detailRule.substring(0, 1);
			String lastLetters = detailRule.substring(rLength-1, rLength);
			String[] rules = detailRule.split(",");
			if (",".equals(firstLetters)) {
				BigDecimal designNumber = BigDecimal.valueOf(Double.valueOf(rules[1]));
				// 成交总额 <= 设定的金额
				if (number.compareTo(designNumber) != 1) {
					// 第一条规则，返回设定的佣金比例
					return cRule;
				}
			} else if (",".equals(lastLetters)) {
				BigDecimal designNumber = BigDecimal.valueOf(Double.valueOf(rules[0]));
				// 成交总额 >= 设定的金额
				if ( number.compareTo(designNumber) != -1) {
					// 最后一条规则，返回设定的佣金比例
					return cRule;
				}
			} else {
				//第二条规则或第N条规则（以后新增的区间），在区间内
				BigDecimal minNumber = BigDecimal.valueOf(Double.valueOf(rules[0]));
				BigDecimal maxNumber = BigDecimal.valueOf(Double.valueOf(rules[1]));
				// 成交金额 >= 设定的最小金额 并且 <= 设定的最大金额
				if (number.compareTo(minNumber) != -1  && number.compareTo(maxNumber) != 1) {
					return cRule;
				}
			}
		}
		//如果只设置了一个规则，当实际成交额超出设定值时，比例直接返回0, 已和业务确认。
		CommissionRules rule = new CommissionRules();
		rule.setCommissionRate("0");
		return rule;
	}
	
	
	/**
	 * 根据成交金额和佣金比例计算佣金
	 * @param amount 成交金额
	 * @param rate 佣金比例
	 * @return String 佣金
	 * @author shaoping.jiao
	 */
	private String calcAmountByRate(BigDecimal amount,String rate){
		BigDecimal bRate = new BigDecimal(Double.valueOf(rate));
		NumberFormat numberFormat = NumberFormat.getInstance();
        // 设置精确到小数点后2位 
        numberFormat.setMaximumFractionDigits(2);
        // 取消千分位
		numberFormat.setGroupingUsed(false);
		return numberFormat.format(amount.multiply(bRate).doubleValue()/100);
	}
	
	
	/**
	 * 查询成交总金额和成交总套数
	 * @param ruleParentId 规则父Id
	 * @param companyId 机构ID
	 * @param premisesId 楼盘ID
	 * @return Commission 佣金信息
	 */
	private Commission selectCommisison(String groupId,Long ruleParentId, Long companyId, Long premisesId) {
		//有规则
		CommissionRuleParent  commissionRuleParent = commissionRuleParentService.selectById(ruleParentId);
		CommissionDto cDto = new CommissionDto();
		cDto.setAgentCompanyId(companyId);
		cDto.setPremisesId(premisesId);
		cDto.setCommissionRuleId(groupId);
		cDto.setBeginTime(commissionRuleParent.getBeginTime());
		cDto.setEndTime(commissionRuleParent.getEndTime());
		cDto.setCommissionStatus(CommissionStatusEnum.no_commission.getNo());
		//有规则，查询对应的佣金
		return commissionService.selectByCompanyIdAndPremisesId(cDto);
	}

}
